package com.apestech.api.file.listener;

import java.io.File;
import java.io.IOException;
import java.nio.file.*;

public abstract class FileListener implements Runnable {
    private WatchService watchService;

    public FileListener(String filePath) {
        try {
            /** 获取文件系统的WatchService对象 **/
            watchService = FileSystems.getDefault().newWatchService();
            /** 向 WatchService 注册监听目录 **/
            register(filePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 功能：向 WatchService 注册监听目录
     *
     * @param filePath
     * @throws Exception
     */
    private void register(String filePath) throws Exception {
        Paths.get(filePath).register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
        File file = new File(filePath);
        if (file.listFiles() == null) return;
        for (File f : file.listFiles()) {
            if (f.isDirectory()) {
                register(f.getAbsolutePath());
            }
        }
    }

    @Override
    public void run() {
        try {
            while (true) {
                /** 获取下一个文件改动事件 **/
                WatchKey watchKey = watchService.take();
                for (WatchEvent<?> event : watchKey.pollEvents()) {
                    try {
                        File file = new File(watchKey.watchable().toString(), event.context().toString());
                        if (file.isDirectory() && event.kind() == StandardWatchEventKinds.ENTRY_CREATE) {
                            register(file.getAbsolutePath());
                        } else {
                            execute(watchKey, event);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                /** 重设WatchKey **/
                boolean valid = watchKey.reset();
                /** 如果重设失败，退出监听 **/
                if (!valid) {
                    break;
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            try {
                watchService.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public abstract void execute(WatchKey watchKey, WatchEvent event);

}
